package org.hawk.gwt.ppc;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import org.hawk.gwt.ppc.Log.LogEngine;
import org.hawk.gwt.ppc.javacc.ParseException;

/**
 * Wraps default GWT compiler into the local wrapper.
 * This allows to create some sort of metadata for the final application.
 * @author alex.bereznevatiy@gmail.com
 */
public class CompilerWrapper {
	private static final String GWT_COMPILER_CLASS_NAME = "com.google.gwt.dev.Compiler";

	/**
	 * @param args
	 * @throws ParseException 
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) 
			throws ParseException, IOException {
		
		CmdArgs argsProcessor = new CmdArgs(args);
		Environment env = Environment.getInstance();
		env.configure(argsProcessor);
		
		Log.printHeader();
		
		try {
			main(env, argsProcessor);
		} catch (NoClassDefFoundError e) {
			Log.error("Unable to find GWT compiller class in the classpath",e);
			System.exit(1);
		} catch(ClassNotFoundException e) {
			Log.error("Unable to find GWT compiller class in the classpath",e);
			System.exit(1);
		} catch(Throwable ex) {
			ex.printStackTrace();
			env.dispose();
			System.exit(1);
		}
	}
	
	/**
	 * This method is only allowed to be launched from maven plugin.
	 * @param params
	 * @throws IOException 
	 * @throws ParseException 
	 */
	@SuppressWarnings("unused")
	private static String runFromMaven(Map<String, Object> params, List<String> modules) throws IOException, ParseException {
		Log.setEngine(LogEngine.MAVEN);
		Environment env = Environment.getInstance();
		try {
			env.configure(new MavenConfiguration(params, modules));
			
			Log.printHeader();
			
			ProcessingUnitsManager.getInstance().run();
			
			return ProcessingUnitsManager.getInstance().getWorkDir().getAbsolutePath();
		} finally {
			env.dispose();
		}
	}

	private static void main(Environment env, CmdArgs argsProcessor)
			throws IOException, ParseException, ClassNotFoundException,
			IllegalAccessException, InvocationTargetException,
			NoSuchMethodException {
		ClassLoader loader = CompilerWrapper.class.getClassLoader();
		try {
			ProcessingUnitsManager manager = ProcessingUnitsManager.getInstance();
			manager.run();
			loader = new ProcessedSourcesLoader(manager.getWorkLoader());
			Thread.currentThread().setContextClassLoader(loader);
		} catch(Throwable th) {
			Log.internalError("GWT preprocessor encounter a fatal error. " +
				"GWT compiller will try to run without preprocessing.\n", th);
		} finally {
			env.dispose();
			gwtCompile(loader, argsProcessor);
		}
	}

	private static void gwtCompile(ClassLoader loader, CmdArgs argsProcessor)
			throws ClassNotFoundException, IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		
		Class<?> cls = loader.loadClass(GWT_COMPILER_CLASS_NAME);
		
		cls.getMethod("main",String[].class).invoke(null,(Object)argsProcessor.getCompillerArguments());
	}
}
